package cn.ad.server.web.spring.service.actions.context;

import cn.ad.server.domain.IPDetail;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Arrays;
import java.util.Comparator;

/**
 * @author dongbin.yu
 * @from 2016-05-30
 * @since V1.0
 */
public class IPContext {

    private IPDetail[] ipDetails;

    private static IPContext ipContext;

    private static final Logger logger = LoggerFactory.getLogger(IPContext.class);

    private IPContext() {

    }

    public static IPContext instance() {

        if (ipContext == null) {
            synchronized (IPContext.class){
                ipContext = new IPContext();
            }
        }

        return ipContext;
    }

    public void init(String path) throws IOException, NullPointerException {
        try(InputStream is = this.getClass().getResourceAsStream(path);
            BufferedReader reader = new BufferedReader(new InputStreamReader(is,"UTF-8"))) {
            String line = null;
            String[] tokens = null;

            int lineNum = 0;
            IPDetail detail = null;

            while ((line = reader.readLine()) != null) {
                tokens = StringUtils.split(line, "\t");

                if(tokens.length == 1) {
                    String total = tokens[0];
                    ipContext.ipDetails = new IPDetail[Integer.parseInt(total)];

                } else if (tokens.length >= 9) {
                    detail = new IPDetail();
                    detail.setStartIp(Long.parseLong(tokens[0]));
                    detail.setEndIp(Long.parseLong(tokens[1]));
                    detail.setCountryId(Integer.parseInt(tokens[2]));
                    detail.setStateId(Integer.parseInt(tokens[3]));
                    detail.setCityId(Integer.parseInt(tokens[4]));
                    detail.setDistrictId(Integer.parseInt(tokens[5]));
                    detail.setUniversityId(Integer.parseInt(tokens[6]));
                    detail.setIpType(Integer.parseInt(tokens[7]));

                    ipContext.ipDetails[lineNum++] = detail;
                } else if (tokens.length >= 8) {

                    detail = new IPDetail();
                    detail.setStartIp(Long.parseLong(tokens[0]));
                    detail.setEndIp(Long.parseLong(tokens[1]));
                    detail.setCountryId(Integer.parseInt(tokens[2]));
                    detail.setStateId(Integer.parseInt(tokens[3]));
                    detail.setCityId(Integer.parseInt(tokens[4]));
                    detail.setDistrictId(Integer.parseInt(tokens[5]));
                    detail.setUniversityId(Integer.parseInt(tokens[6]));
                    detail.setDescription(tokens[7]);

                    ipContext.ipDetails[lineNum++] = detail;
                }
            }
        } catch (FileNotFoundException e) {
            logger.error("ipDetails txt could not found");
            throw e;
        } catch (IOException e) {
        	logger.error("could not open ipDetails txt");
        	throw e;
        }

    }

    public IPDetail getIPDetail(long ip) {

        IPDetail ipDetail = new IPDetail();
        ipDetail.setStartIp(ip);
        ipDetail.setEndIp(ip);

        int index = Arrays.binarySearch(ipDetails, ipDetail, new Comparator<IPDetail>() {
            @Override
            public int compare(IPDetail o1, IPDetail o2) {

                return o2.getStartIp() > o1.getEndIp() ? -1
                        : ((o1.getStartIp() > o2.getStartIp() || o1.getEndIp() < o2.getStartIp())
                        && (o2.getStartIp() > o1.getStartIp() || o2.getEndIp() < o1.getStartIp()) ? (o1.getStartIp() > o2.getEndIp() ? 1 : 0) : 0);
            }
        });

        return index < 0 ? null : ipDetails[index];
    }

}
